package org.raymond.iworks.study.basic.thread.locksupport;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author raymond
 * @version V1.0
 * @Description: TODO
 */

/**
 * park()与unpark()方法:只要线程存在许可证,不管是在park()方法前或者调用park()方法后拥有,线程都会继续执行.
 * wait()与notify()方法:wait()方法必须要在notify()方法之前执行,否则wait()方法错失信号,进入无限等待状态,从而产生死锁
 */
@Slf4j
public class AwaitSignal {
    private static ReentrantLock lock = new ReentrantLock();
    private static Condition condition = lock.newCondition();

    public static void main(String[] args) throws InterruptedException {
        test2();
    }

    public static void test1() throws InterruptedException{
        Thread t1 = new Thread(()->{
            lock.lock();
            try{
                log.info("await start...");
                condition.await();
                log.info("await end...");
            }catch(Exception e){
                log.error("{}", e.getMessage());
            }finally {
                lock.unlock();
            }
        });
        Thread t2 = new Thread(()->{
            log.info("signalAll start...");
            lock.lock();
            try {
                condition.signalAll();
            }finally {
                lock.unlock();
            }
            log.info("signalAll end...");
        });
        log.info("start await");
        t1.start();

        log.info("sleep...");
        Thread.sleep(1*1000);

        log.info("start signal");
        t2.start();
    }

    public static void test2() throws InterruptedException {
        ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 2, 0, TimeUnit.MICROSECONDS, new LinkedBlockingQueue<>());
        pool.execute(()->{
            lock.lock();
            try{
                log.info("f1 start await");
                condition.await();
                log.info("f1 start end");
            }catch(InterruptedException e){
                log.error("{}", e.getMessage());
            }finally {
                lock.unlock();
            }
        });
        pool.execute(()->{
            lock.lock();
            try{
                log.info("f2 start await");
                condition.await();
                log.info("f2 start end");
            }catch(InterruptedException e){
                log.error("{}", e.getMessage());
            }finally {
                lock.unlock();
            }
        });

        Thread.sleep(1000);
        lock.lock();
        try {
            log.info("f3 signalAll await");
            condition.signalAll();
            log.info("f3 signalAll await");
        }finally {
            lock.unlock();
        }
        pool.shutdown();
    }
}
